
#include "USBDevice.h"
#include "GQueue.h"
#include "HidFFB.h"
#include "FFBWheelMain.h"
// USB Callbacks
extern USBdevice usbDevice;
extern gqueue_t qxdRcv;
extern ffb_wheel_t ffbWheel;
USBdevice* usb_device=&usbDevice;

void HidFFB_hidOut(HidFFB* ffb,uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize);
uint16_t HidFFB_hidGet(HidFFB* ffb,uint8_t report_id, hid_report_type_t report_type,uint8_t* buffer, uint16_t reqlen);

uint8_t const * tud_descriptor_device_cb(void){
  return (uint8_t const*)getUsbDeviceDesc();
}

uint8_t const * tud_descriptor_configuration_cb(uint8_t index){
	return getUsbConfigurationDesc(0);
}

uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid){

	return getUsbStringDesc(index,langid);
}

uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf){
	return getUsbHidReportDesc();
}

extern void xd_Rcv_Sem(void);
uint8_t cdcTempBuf[64];
void tud_cdc_rx_cb(uint8_t itf){

	uint32_t count = tud_cdc_n_read(itf,cdcTempBuf, sizeof(cdcTempBuf));
	gqueue_push_multiple(&qxdRcv,cdcTempBuf,count,(size_t*)&count);
	xd_Rcv_Sem();
}

void tud_cdc_tx_complete_cb(uint8_t itf){


}



/**
 * USB Out Endpoint callback
 * HID Out and Set Feature
 */
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize){
	if(report_type == HID_REPORT_TYPE_INVALID && report_id == 0)
	{
		report_id = *buffer;
	}
	HidFFB_hidOut(&ffbWheel.ffb,report_id,report_type,buffer,bufsize);

    //通过HID设置参数，未实现
//  if(report_id == HID_ID_HIDCMD){
//      if(HID_CommandInterface::globalInterface != nullptr)
//          HID_CommandInterface::globalInterface->hidCmdCallback((HID_CMD_Data_t*)(buffer));
//  }


}

/**
 * HID Get Feature
 */
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type,uint8_t* buffer, uint16_t reqlen){

	return HidFFB_hidGet(&ffbWheel.ffb,report_id, report_type, buffer,reqlen); // reply buffer should not contain report ID in first byte
}

/**
 * HID transfer complete
 */
void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len){
//	if(HID_CommandInterface::globalInterface != nullptr){
//		HID_CommandInterface::globalInterface->transferComplete(itf, report, len);
//	}
//	if(UsbHidHandler::globalHidHandler != nullptr){
//		UsbHidHandler::globalHidHandler->transferComplete(itf, report, len);
//	}
}

#ifdef MIDI
//MidiHandler* midihandler = nullptr;
/**
 * Midi receive callback
 */
void tud_midi_rx_cb(uint8_t itf){
//	if(!midihandler) return;

//	if(tud_midi_n_packet_read(itf,MidiHandler::buf)){
//		midihandler->midiRx(itf, MidiHandler::buf);
//	}
}
#endif

extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
/**
 * Called on usb disconnect and suspend
 */
void tud_suspend_cb(bool en){
//    HAL_PCD_Stop(&hpcd_USB_OTG_FS);
//    rt_thread_delay(50);
//    HAL_PCD_Start(&hpcd_USB_OTG_FS);
}
void tud_umount_cb()
{

}

/**
 * Called on usb mount
 */
void tud_mount_cb()
{

}


void tud_resume_cb()
{

}

